﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;


namespace Knlght.Web.Infrastructure.Menus
{
    /*
      * app_data的 menu.json 文件中反序列化出菜单
      */

    /// <summary>
    /// 菜单提供器
    /// </summary>
    public class MenuProvider
    {
        public const string Path = "/App_Data/mall_admin_menu.json";
        public static MenuProvider Instance;
        public static readonly object AsyncObj = new object();
        private readonly MenuItem[] _mallAdminMenu;
        public readonly Dictionary<string, MenuItem> MallAdminMenuMap;

        private MenuProvider()
        {
            string fullPath = HttpContext.Current.Server.MapPath(Path);
            //从指定的数据路径中加载菜单
            var sr = new System.IO.StreamReader(fullPath);
            var serializer = new Newtonsoft.Json.JsonSerializer();
            var list = serializer.Deserialize(sr, typeof(List<MenuItem>)) as List<MenuItem>;
            if (list != null) _mallAdminMenu = list.ToArray();
            MallAdminMenuMap = new Dictionary<string, MenuItem>();
            LoadMenuItem(MallAdminMenuMap, null, _mallAdminMenu);
        }
        private static MenuProvider Current
        {
            get
            {
                if (Instance != null) return Instance;
                lock (AsyncObj)
                {
                    if (Instance == null)
                    {
                        Instance = new MenuProvider();
                    }
                }
                return Instance;
            }
        }

        /// <summary>
        /// 商城后台管理菜单
        /// </summary>
        public static MenuItem[] MallAdminMenu => Current._mallAdminMenu;

        /// <summary>
        /// 获取指定商城后台菜单项
        /// </summary>
        public static MenuItem GetMallAdminItemItem(string key)
        {
            if (!Current.MallAdminMenuMap.ContainsKey(key))
            {
                throw new ApplicationException($"无法找到{key}对应的菜单项!");
            }
            return Current.MallAdminMenuMap[key];
        }
        /// <summary>
        /// 获取指定商城后台菜单项路径集合(从最顶级的父类，到当前菜单项排序)
        /// </summary>
        public static MenuItem[] GetMallAdminAllMenuItemsBy(string key)
        {
            var mi = GetMallAdminItemItem(key);
            var mis = new List<MenuItem> {mi};
            var parent = mi.Parent;
            while (parent != null)
            {
                mis.Add(parent);
                parent = parent.Parent;
            }
            mis.Reverse();  //反转集合，让菜单从最顶级的父类到当前菜单，依次排序
            return mis.ToArray();
        }

        #region 私有方法
        //加载菜单的各项到内存中
        public void LoadMenuItem(Dictionary<string, MenuItem> map, MenuItem parent, IEnumerable<MenuItem> menuItems)
        {
            if (map == null) throw new ArgumentNullException(nameof(map));
            foreach (var mi in menuItems)
            {
                var errors = mi.Check();
                if (errors != null && errors.Count > 0)
                {
                    var sb = new StringBuilder();
                    sb.AppendLine("菜单格式错误");
                    errors.ForEach(o => sb.AppendLine(o));
                    throw new ApplicationException(sb.ToString());
                }

                if (map.ContainsKey(mi.ID))
                {
                    var sb = new StringBuilder();
                    sb.AppendLine("菜单格式错误");
                    sb.AppendLine($"菜单项{mi.ID}存在重复的键!");
                    throw new ApplicationException(sb.ToString());
                }
                mi.Parent = parent;
                map.Add(mi.ID, mi);

                if (mi.Children != null && mi.Children.Count > 0)
                {
                    LoadMenuItem(map, mi, mi.Children);
                }
            }
        }

        #endregion
    }
}
